// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_META_TABLET_SCANNER_HPP_
#define _XBASE_META_TABLET_SCANNER_HPP_

#include <list>

#include <boost/function.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/system/error_code.hpp>

#include "scan_struct.hpp"
#include "sync_handler.hpp"
#include "tablet_scanner.hpp"
#include "session_manager.hpp"
#include "io_service_pool.hpp"
#include "async_module_base.hpp"

namespace xbase
{
	class meta_tablet_scanner
		: public async_module_base<io_service_pool::xbase_level, io_service_pool::xbase_level>
	{
	public:
		typedef async_module_base<io_service_pool::xbase_level, io_service_pool::xbase_level> base_type;
		typedef meta_tablet_scanner this_type;
		typedef boost::intrusive_ptr<this_type> ptr_type;

		typedef tablet_scanner::ptr_type tablet_scanner_ptr;
		typedef session_manager::endpoint_type endpoint_type;

		typedef boost::system::error_code error_code;

		typedef boost::function<void(meta_row_result::ptr_type, const error_code&)> handler_type;
		typedef std::list<handler_type> handler_list;

		typedef basic_sync_handler<meta_row_result::ptr_type> sync_handler_type;

	public:
		meta_tablet_scanner(io_service_pool &pool,
				    const endpoint_type &ep,
				    session_manager &sm,
				    const std::string &start_row,
				    const std::string &end_row);

		void async_get_next_row(handler_type handler)
		{
			m_tablet_scanner_ptr->async_get_next_row(boost::bind(&this_type::on_get_next_row, this_ptr(), handler, _1, _2));
		}

		error_code get_next_row(meta_row_result::ptr_type &row_ptr)
		{
			async_get_next_row(m_sync_handler.make_handler());
			m_sync_handler.wait();

			row_ptr = m_sync_handler.get_meta_row_result_ptr();
			error_code ec = m_sync_handler.get_error_code();

			return ec;
		}

		unsigned get_valid_row_count()
		{
			return m_valid_row_count;
		}

	private:
		void on_get_next_row(handler_type handler, row_result::ptr_type row_ptr, const error_code &ec);

	protected:
		ptr_type this_ptr() {
			return ptr_type(this);
		}

	private:
		io_service_pool &m_io_service_pool;
		tablet_scanner_ptr m_tablet_scanner_ptr;
		meta_row_result::ptr_type m_meta_row_ptr;
		unsigned m_valid_row_count;
		sync_handler_type m_sync_handler;
	};

	typedef meta_tablet_scanner::ptr_type meta_tablet_scanner_ptr;
}

#endif

